package com.lenovo.tool;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class TranslationReplace {
    // Compare target and src XML files, and then find out those elements
    // with different translations in src XML file and output them to diff XML
    // file
    
	private static final String TAG_STRING = "string";
	private static final String TAG_STRING_ARRAY = "string-array";
	private static final String TAG_PLURALS = "plurals";
	private static final String doubleQuota = "\"";
	private static boolean needSaveFile = false;
	
    private static void saveReplaceStringsToFile(File baseFile,String keyword,String replace) {
        try {
            Document baseDoc = DocumentUtils.openDocument(baseFile);
            Element root = baseDoc.getDocumentElement();
            
            needSaveFile = false;
			replaceElement(root,keyword, replace);     
            if (!needSaveFile){
                return;
            }
            
            System.out.println(baseFile.getAbsolutePath());
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer();           
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            DOMSource source = new DOMSource(baseDoc);
            StreamResult result = new StreamResult(baseFile);
            transformer.transform(source, result);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }

    }

    public static void findReplaceTranslations(File baseDir,ArrayList<String> localeList, 
    		ArrayList<String> excludePathList,String keyword,String replace) throws IOException {
    	if (null == keyword || null == replace){
            return;
 		}
        XmlResFileFilter filter = new XmlResFileFilter(true);

        for (String path : excludePathList) {
            filter.addExludePath(path);
        }

        ArrayList<File> baseFiles = filter.getLocaleXmlResFiles(baseDir,
                localeList);

        for (File baseFile : baseFiles) {
            saveReplaceStringsToFile(baseFile,keyword,replace);            
        }
    }
	
	public static void replaceStringElement(Element root,String keyword,String replace){ 
		Element element = root;    
		//System.out.println(root.getTextContent());
		String sourceString = root.getTextContent();
		if (null == sourceString || !sourceString.contains(keyword)
			||	!sourceString.startsWith(doubleQuota)
			||  !sourceString.endsWith(doubleQuota)){
		    return;
		}		
		for (int i=0;i<element.getChildNodes().getLength();i++){
			Node node = element.getChildNodes().item(i);
			if (null != node && node.getNodeType() == Node.TEXT_NODE){
				replaceNodeValue(node,keyword,replace);
			}else if (null != node && node.getNodeType() == Node.ELEMENT_NODE){
				replaceElement((Element)node,keyword,replace);
			}
		}
	}

	public static void replaceArrayElement(Element root,String keyword,String replace){
		Element element = root; 
		NodeList item_list = element.getElementsByTagName("item");
		for (int i=0;i<item_list.getLength();i++){
			Element elementItem = (Element)item_list.item(i);
			System.out.println(elementItem.getTextContent());
			String sourceString = elementItem.getTextContent();
			if (null == sourceString || !sourceString.contains(keyword)
				||	!sourceString.startsWith(doubleQuota)
				||  !sourceString.endsWith(doubleQuota)){
			    continue;
			}		
			for (int j=0;j<elementItem.getChildNodes().getLength();j++){
				Node arrayNode = elementItem.getChildNodes().item(j);                    	
				if (null != arrayNode && arrayNode.getNodeType() == Node.TEXT_NODE){
					replaceNodeValue(arrayNode,keyword,replace);
				}else if (null != arrayNode && arrayNode.getNodeType() == Node.ELEMENT_NODE){
					replaceElement((Element)arrayNode,keyword,replace);
				}
			}
		}
	}

	public static void replacePluralElement(Element root,String keyword,String replace){           	
		Element element = root; 
		NodeList item_list = element.getElementsByTagName("item");
		for (int j=0;j<item_list.getLength();j++){
			Element elementItem = (Element)item_list.item(j);
			System.out.println(elementItem.getTextContent());
			String sourceString = elementItem.getTextContent();
			if (null == sourceString || !sourceString.contains(keyword)
				||	!sourceString.startsWith(doubleQuota)
				||  !sourceString.endsWith(doubleQuota)){
			    continue;
			}		
			for (int k=0;k<elementItem.getChildNodes().getLength();k++){
				Node pluralsNode = elementItem.getChildNodes().item(k); 
				if (null != pluralsNode && pluralsNode.getNodeType() == Node.TEXT_NODE){
					replaceNodeValue(pluralsNode,keyword,replace);
				}else if (null != pluralsNode && pluralsNode.getNodeType() == Node.ELEMENT_NODE){
					replaceElement((Element)pluralsNode,keyword,replace);
				}
				
			}
				
		}
	}

    public static void replaceElement(Element root,String keyword,String replace){
		if (null == root || !root.hasChildNodes()){
			return;
		}
		for (int i=0;i<root.getChildNodes().getLength();i++){
			Node child = root.getChildNodes().item(i);
			if (null != child && child.getNodeType() == Node.TEXT_NODE){
				replaceNodeValue(child,keyword,replace);
				continue;
			}
			if (null != child && child.getNodeType() == Node.ELEMENT_NODE){
				if (((Element)child).getTagName().equals(TAG_STRING)){
					replaceStringElement((Element)child,keyword,replace);
				}
				else if (((Element)child).getTagName().equals(TAG_STRING_ARRAY)){
					replaceArrayElement((Element)child,keyword,replace);
				}
				else if (((Element)child).getTagName().equals(TAG_PLURALS)){
					replacePluralElement((Element)child,keyword,replace);
				}else {
					replaceElement((Element)child,keyword,replace);
				}
			}
		}
	}
		 
    public static void replaceNodeValue(Node node,String keyword,String replace){ 
		if (null != node && node.getNodeType() == Node.TEXT_NODE){
			String sourceString = node.getNodeValue();
			if (null == sourceString ){
			    return;
			}
			if (!needSaveFile ){
				needSaveFile = true;
			}
			sourceString = sourceString.replace(keyword, replace);
			node.setNodeValue(sourceString);
		}
    }
	
    public static void main(String[] args)  {
        if (args.length != 1) {
            System.out.println("please enter the config file name");
            return;
        }

        File configFile = new File(args[0]);
        //File configFile = new File("D:\\Users\\lenovo6\\workspace\\TranslationTool\\replace_translation.xml");        
        if (!configFile.exists() || !configFile.isFile()) {
            System.out.println("config file error");
            return;
        }

        try {
            PropConfigHandler handler = new PropConfigHandler();

            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            parser.parse(configFile, handler);

            Properties props = handler.getProps();
            ArrayList<String> excludePathList = handler.getExcludePaths();

            File baseDir = new File(props.getProperty("basedir"));
            String locales = props.getProperty("locales");
            ArrayList<String> localeList = new ArrayList<String>();
            if (locales != null) {
                StringTokenizer tokenizer = new StringTokenizer(locales, ",");
                while (tokenizer.hasMoreTokens()) {
                    localeList.add(tokenizer.nextToken());
                }
            }
            String keyword = props.getProperty("keyword");
            String replace = props.getProperty("replace");
            findReplaceTranslations(baseDir, localeList, excludePathList,keyword,replace);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
